package com.sne.common.util;

import com.sne.common.constant.ScheduleConstants;
import com.sne.common.exception.CustomException;
import com.sne.common.task.QuartzDisallowConCurrentExecution;
import com.sne.common.task.QuartzJobExecution;
import com.sne.monitor.entity.MonitorTimeTask;
import lombok.experimental.UtilityClass;
import org.quartz.*;

/**
 * 定时任务工具类
 * @author fanghh
 * @date 2020/12/11
 */
@UtilityClass
public class ScheduleUtil {

    /**
     * 获取quartz任务类
     * @param timeTask 执行计划
     * @return Class
     */
    private Class<? extends Job> getQuartzJobClass(MonitorTimeTask timeTask){
        return timeTask.getConcurrence()? QuartzJobExecution.class: QuartzDisallowConCurrentExecution.class;
    }

    /**
     * 任务触发对象
     * @param jobId 任务id
     * @param jobGroup 任务分组
     * @return TriggerKey
     */
    public TriggerKey getTriggerKey(Long jobId,String jobGroup){
        return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME+jobId,jobGroup);
    }

    /**
     * 获取任务key对象
     * @param jobId 任务id
     * @param jobGroup 任务分组
     * @return JobKey
     */
    public JobKey getJobKey(Long jobId,String jobGroup){
        return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME+jobId,jobGroup);
    }

    /**
     * 创建定时任务
     * @param scheduler 定时任务调度器
     * @param timeTask 定时任务
     * @throws SchedulerException 定时任务异常
     */
    public void createScheduleJob(Scheduler scheduler,MonitorTimeTask timeTask) throws SchedulerException {
        Class<? extends Job> jobClass = getQuartzJobClass(timeTask);
        Long jobId = timeTask.getId();
        String jobGroup = timeTask.getTaskGroup();
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId,
                jobGroup)).build();

        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(timeTask.getCron());
        cronScheduleBuilder = handleCronScheduleMisfirePolicy(timeTask, cronScheduleBuilder);
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup))
                .withSchedule(cronScheduleBuilder).build();

        jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES,timeTask);
        if(scheduler.checkExists(getJobKey(jobId,jobGroup))){
            scheduler.deleteJob(getJobKey(jobId,jobGroup));
        }
        scheduler.scheduleJob(jobDetail,trigger);
        if(!timeTask.getState()){
            scheduler.pauseJob(getJobKey(jobId,jobGroup));
        }
    }

    /**
     * 设置定时任务策略
     * @param task 任务
     * @param cb 表达式构建器
     * @return CronScheduleBuilder
     */
    public CronScheduleBuilder handleCronScheduleMisfirePolicy(MonitorTimeTask task,CronScheduleBuilder cb){
        switch (task.getStragtery()){
            case ScheduleConstants.MISFIRE_DEFAULT:
                return cb;
            case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
                return cb.withMisfireHandlingInstructionIgnoreMisfires();
            case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
                return cb.withMisfireHandlingInstructionFireAndProceed();
            case ScheduleConstants.MISFIRE_DO_NOTHING:
                return cb.withMisfireHandlingInstructionDoNothing();
            default:
                throw new CustomException(task.getStragtery()+"获取失败");
        }
    }

}
